import log from 'electron-log/main';
import GlobalConstant from '../core/GlobalConstant';
import { stopPythonServer } from './pythonService';
import { app } from 'electron';

let isCleaning = false;
let cleaningPromise: Promise<void> | null = null;
let hasQuit = false;

export async function ensureCleanup(
  cleanupFunctions: Array<() => void> = [],
  reason = 'unknown',
) {
  if (isCleaning && cleaningPromise) {
    return cleaningPromise;
  }

  log.info(`应用退出触发，原因: ${reason}`);

  isCleaning = true;
  cleaningPromise = (async () => {
    try {
      for (const cleanup of cleanupFunctions) {
        try {
          await cleanup();
        } catch (error) {
          log.error('执行清理函数时出错:', error);
        }
      }

      if (!GlobalConstant.USE_EXTERNAL_SDK) {
        try {
          await stopPythonServer();
        } catch (error) {
          log.error('停止 Python 服务器时出错:', error);
        }
      }

      log.info('清理完成，应用程序退出');
    } catch (error) {
      log.error('清理时出错:', error);
    } finally {
      isCleaning = false;
      cleaningPromise = null;
      if (!hasQuit) {
        hasQuit = true;
        app.quit(); // 防止重复退出
      }
    }
  })();

  return cleaningPromise;
}

export function setupCleanupHandlers(cleanupFunctions: Array<() => void> = []) {
  /*
  作用：当一个未被捕获的异常（没有 try-catch 处理的错误）在主进程中发生时，Node.js 会触发这个事件。
  用途：通常用来捕获未处理的异常，以避免进程直接崩溃。可以用来记录错误或执行清理任务。
   */
  process.on('uncaughtException', async (error) => {
    console.error('未捕获异常:', error);
    await ensureCleanup(cleanupFunctions, 'uncaughtException');
  });

  /*
  作用：当 Promise 被拒绝且没有 .catch() 捕获时触发。该事件使你能够捕获 Promise 的未处理拒绝。
  用途：用于处理未处理的 Promise 拒绝，防止 Node.js 启动时未处理的 Promise 拒绝导致的退出。
   */
  process.on('unhandledRejection', async (reason, promise) => {
    console.error('未处理的 Promise 拒绝:', reason);
    await ensureCleanup(cleanupFunctions, 'unhandledRejection');
  });

  /*
  作用：这是一个终端信号，当你在终端按下 Ctrl+C 时发送给应用。它是一个中断信号。
  用途：通常用来捕获应用程序的退出请求，执行必要的清理任务（如关闭文件、数据库连接等）。
   */
  process.on('SIGINT', async () => {
    console.warn('接收到 SIGINT');
    await ensureCleanup(cleanupFunctions, 'SIGINT');
  });

  /*
  作用：SIGTERM 是请求进程退出的信号，通常由操作系统或其他进程发送。当应用需要关闭时，可以优雅地处理此信号，确保在退出前清理资源。
  用途：用于处理进程退出的信号，执行退出前的清理操作。
   */
  process.on('SIGTERM', async () => {
    console.warn('接收到 SIGTERM');
    await ensureCleanup(cleanupFunctions, 'SIGTERM');
  });

  /*
  作用：当 Node.js 进程准备退出时触发，但在事件循环没有完全清空前触发。可以用于执行清理操作。
  用途：允许在进程退出前执行一些最后的清理任务，但在退出前可以有一些异步操作。
   */
  process.on('beforeExit', async () => {
    console.log('beforeExit 事件触发');
    await ensureCleanup(cleanupFunctions, 'beforeExit');
  });

  /*
  作用：当 Node.js 进程退出时触发。你可以在 exit 事件中执行清理任务，但是这个事件是同步的，不能执行异步操作。
  用途：通常用于确保同步清理操作，如日志记录、关闭文件等。
   */
  process.on('exit', () => {
    log.info('exit 事件触发，Node.js 进程退出');
  });

  let isQuitInitiated = false;

  /*
  作用：在 Electron 应用程序关闭前触发，允许在退出前进行清理任务。
  用途：适用于需要在退出前执行清理（例如保存数据、关闭连接）的场景。你可以通过 event.preventDefault() 阻止退出，直到清理完成后再继续。
   */
  app.on('before-quit', async (event) => {
    if (isQuitInitiated) return;
    isQuitInitiated = true;

    console.log('before-quit 事件触发');
    event.preventDefault();
    await ensureCleanup(cleanupFunctions, 'before-quit');
    app.quit(); // 手动退出
  });

  /*
  作用：用于监听文件描述符、流等对象关闭时的事件。
  用途：常用于流的关闭事件，比如文件流、网络连接等。
   */
  // window.on('close', async (event) => {
  //     log.info('close 事件触发，应用程序关闭...');
  //     event.preventDefault();  // 阻止窗口立即关闭
  //     await ensureCleanup(cleanupFunctions,);  // 等待清理完成
  //     window.destroy();  // 完成清理后销毁窗口
  // });

  /*
  作用：当 Electron 应用完全退出时触发。此事件在应用退出的最后阶段触发，不再有机会做任何清理。
  用途：常用于日志记录或应用退出后的最后操作。
   */
  app.on('quit', async () => {
    console.log('quit 事件触发');
    // 通常 quit 后无法阻止退出，清理建议在 before-quit 中做
  });

  /*
  作用：当所有的窗口都被关闭时触发（在某些平台上，比如 Windows，关闭所有窗口时应用会退出）。
  用途：在关闭所有窗口后，可以决定是否退出应用或保持后台运行（例如在 Mac 上，应用通常保持后台运行）。
   */
  app.on('window-all-closed', () => {
    console.log('所有窗口已关闭');
    // 通常在这里调用 app.quit()（除非 macOS）
    if (process.platform !== 'darwin') {
      app.quit();
    }
  });
}
